﻿<#.SYNOPSIS      BackUp script for SharePoint 2010 & 2013.DESCRIPTION  	SPSWakeUp is a PowerShell script tool to warm up all site collection in your SharePoint environment.	Log script results in rtf file, 	Email nofications.PARAMETER inputFile	Need parameter input file, example: 	PS D:\> E:\SCRIPT\SPSBackUP.ps1 "E:\SCRIPT\SPSBackUP.xml".EXAMPLE	SPSBackUP.ps1 "E:\SCRIPT\SPSBackUP.xml".NOTES  	FileName:	SPSBackUP.ps1	Author:		Jean-Cyril DROUHIN	Date:		March 06, 2015	Version:	1.1	Licence:	MS-PL.LINK	https://spsbackup.codeplex.com/#>	param (    [Parameter(Mandatory=$true,Position=0)][string]$inputFile = $(throw '- Need parameter input file'))# Get the content of the SPSWarmUP-INPUT.xml file[xml]$xmlinput = (Get-Content $inputFile -ReadCount 0)# ====================================================================================# INTERNAL FUNCTIONS
# ====================================================================================
# Region Get-SPSUserPassword# ===================================================================================# Func: Get-SPSUserPassword# Desc: Get Password from Service Account# ===================================================================================
Function Get-SPSUserPassword ([string]$user)
{
    [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
    $password = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the password of $user", "User Account Information", "")
    #$password = Read-Host -assecurestring "Please enter your password of $user"

    If (($password -ne "") -and ($user -ne ""))
    {
        $currentDomain = "LDAP://" + ([ADSI]"").distinguishedName
        Write-Host -ForegroundColor White " - Account `"$user`" ..." -NoNewline
        $dom = New-Object System.DirectoryServices.DirectoryEntry($currentDomain,$user,$password)
        If ($dom.Path -eq $null)
        {
            Write-Host -BackgroundColor Red -ForegroundColor Black "Invalid!"
            $acctInvalid = $true
        }
        Else
        {
            Write-Host -ForegroundColor Black -BackgroundColor Green "Verified."
        }
    }

    Return $password
}

# Region Add-SPSTask# ===================================================================================# Func: Add-SPSTask# Desc: Add SPSBackUP Task in Task Scheduler# ===================================================================================Function Add-SPSTask{	Param 	(		[Parameter(Mandatory=$true,Position=0)][string]$Path,        [Parameter(Mandatory=$true,Position=1)][xml]$InputFile	)

    If($InputFile.Configuration.Install.Enable -eq "true")	{        
        $TaskDate = Get-Date -Format yyyy-MM-dd
        $TaskName = "SPSBackUP"
        $Hostname = $Env:computername

        # Connect to the local TaskScheduler Service
        $TaskSvc = New-Object -ComObject ("Schedule.service")
        $TaskSvc.Connect($Hostname)
        $TaskFolder = $TaskSvc.GetFolder("\")
        $TaskSPSWKP = $TaskFolder.GetTasks(0) | Where-Object -Property Name -eq $TaskName
        $TaskCmd = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
        $TaskCmdArg = 
@"
-Command Start-Process "$PSHOME\powershell.exe" -Verb RunAs -ArgumentList "'-ExecutionPolicy Bypass $path\SPSBackUP.ps1 $path\SPSBackUP.xml'"
"@

        If ($TaskSPSWKP)
        {
            # Write-Host -ForegroundColor Yellow "   * Shedule Task already exists - skipping."
        }
        Else
        {
			Write-Host -ForegroundColor White "--------------------------------------------------------------"			Write-Host -ForegroundColor White " - Adding SPSWakeUP script in Task Scheduler Service ..."

			# Get Credentials for Task Schedule
			$TaskAuthor = ([Security.Principal.WindowsIdentity]::GetCurrent()).Name
			$TaskUser =  $InputFile.Configuration.Install.ServiceAccount
			$TaskUserPwd = Get-SPSUserPassword $TaskUser

            # Add a New Task Schedule
            $TaskSchd = $TaskSvc.NewTask(0)
            $TaskSchd.RegistrationInfo.Description = "SPSWakeUp Task - Start at 6:00 daily"
            $TaskSchd.RegistrationInfo.Author = $TaskAuthor
            $TaskSchd.Principal.RunLevel = 1

            # Task Schedule - Modify Settings Section
            $TaskSettings = $TaskSchd.Settings
            $TaskSettings.AllowDemandStart = $true
            $TaskSettings.Enabled = $true
            $TaskSettings.Hidden = $false
            $TaskSettings.StartWhenAvailable = $true

            # Task Schedule - Trigger Section
            $TaskTriggers = $TaskSchd.Triggers

            # Add Trigger Type 2 OnSchedule Daily Start at 22:00 AM
            $TaskTrigger1 = $TaskTriggers.Create(2)
            $TaskTrigger1.StartBoundary = $TaskDate + "T22:00:00"
            $TaskTrigger1.DaysInterval = 1
            $TaskTrigger1.Enabled = $true

            $TaskAction = $TaskSchd.Actions.Create(0)
            $TaskAction.Path = $TaskCmd
            $TaskAction.Arguments = $TaskCmdArg
            Try
            {
                $TaskFolder.RegisterTaskDefinition( $TaskName, $TaskSchd, 6, $TaskUser , $TaskUserPwd , 1)
                Write-Host -ForegroundColor Green "   * Successfully added SPSWakeUP script in Task Scheduler Service"
            }
            Catch		    {                Write-Warning "An error occurred adding Scheduled Task for `"$TaskUser`""			                    Write-Host -ForegroundColor Yellow "$_"		    }
        }
    }
}
# End Region

# Region Load SharePoint Powershell Snapin for SharePoint 2010 & 2013
# ===================================================================================
# Name: 		Load SharePoint Powershell Snapin
# Description:	Load SharePoint Powershell Snapin
# ===================================================================================
Function Load-SharePoint-Powershell
{
    If ((Get-PsSnapin |?{$_.Name -eq "Microsoft.SharePoint.PowerShell"})-eq $null)
    {
        Write-Host -ForegroundColor White "--------------------------------------------------------------"
        Write-Host -ForegroundColor White " - Loading SharePoint Powershell Snapin..."
        Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction Stop | Out-Null
        Write-Host -ForegroundColor White "--------------------------------------------------------------"
    }
}
# Region End

# Region Get All Web Applications Url
# ===================================================================================
# Name: 		Get All Web Applications Url
# Description:	Get All Web Applications Url
# ===================================================================================
Function Get-AllWebAppURL
{
	Write-Host -ForegroundColor White "--------------------------------------------------------------"
	Write-Host -ForegroundColor White " - Get URLs of All Web Applications..."
	$WebAppURL = new-Object System.Collections.ArrayList

	# get web services from local farm
	$WebApps = Get-SPWebApplication -IncludeCentralAdministration
	
	foreach ($WebApp in $WebApps) 
	{
		[void]$WebAppURL.Add($WebApp.Url)
	}
    return $WebAppURL
	Write-Host -ForegroundColor White " "	
}
# Region End

# Region Add-SPSUserPolicy# ===================================================================================# Func: Add-SPSUserPolicy# Desc: Applies Read Access to the specified accounts for a web application# ===================================================================================Function Add-SPSUserPolicy($urls){	Write-Host -ForegroundColor White "--------------------------------------------------------------"	Write-Host -ForegroundColor White " - Add Read Access to $currentuser for All Web Applications ..."	ForEach ($url in $urls)	{		Try		{			$webapp = [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup("$url")			$user = ([Security.Principal.WindowsIdentity]::GetCurrent()).Name			$displayName = "WarmUp Account"			$perm = "Full Read"						# If the web app is not Central Administration 			If ($webapp.IsAdministrationWebApplication -eq $false)			{				# If the web app is using Claims auth, change the user accounts to the proper syntax				If ($webapp.UseClaimsAuthentication -eq $true)				{					$user = 'i:0#.w|'+$user				}				Write-Host -ForegroundColor White " - Applying Read access for $user account to $url..."				[Microsoft.SharePoint.Administration.SPPolicyCollection]$policies = $webapp.Policies				$PolicyExist = $policies | where {$_.Displayname -eq "WarmUp Account"}								If ($PolicyExist)				{					Write-Host -ForegroundColor Yellow "   * Read access for WarmUp Account already exists - skipping."				}				Else				{					[Microsoft.SharePoint.Administration.SPPolicy]$policy = $policies.Add($user, $displayName)					[Microsoft.SharePoint.Administration.SPPolicyRole]$policyRole = $webapp.PolicyRoles | where {$_.Name -eq $perm}					If ($policyRole -ne $null)					{						$policy.PolicyRoleBindings.Add($policyRole)					}					$webapp.Update()					Write-Host -ForegroundColor White "   * Done Applying Read access for `"$user`" account to `"$url`""				}			}		}		Catch		{			$_			Write-Warning "An error occurred applying Read access for `"$user`" account to `"$url`""		}	}}# Region End

# Region Send-SPSLogs# ===================================================================================# Func: Send-SPSLogs# Desc: Send Email with log file in attachment# ===================================================================================Function Send-SPSLogs{	Param 	(		[Parameter(Mandatory=$true,Position=0)][xml]$inputFile,		[Parameter(Mandatory=$true,Position=1)]$MailAttachment,		[Parameter(Mandatory=$true,Position=2)]$MailBody	)		If($inputFile.Configuration.EmailNotification.Enable -eq $true)	{		$MailAddress = $inputFile.Configuration.EmailNotification.EmailAddress		$SMTPServer = $inputFile.Configuration.EmailNotification.SMTPServer		$MailSubject = "Automated Script - WarmUp Urls - $env:COMPUTERNAME"		Write-Host -ForegroundColor White "--------------------------------------------------------------"		Write-Host -ForegroundColor White " - Sending Email with Log file to $MailAddress ..."		Try		{			$SendLogs = Send-MailMessage -To $MailAddress -From $MailAddress -Subject $MailSubject -Body $MailBody -BodyAsHtml -SmtpServer $SMTPServer -Attachments $MailAttachment -ea stop			Write-Host -ForegroundColor Green " - Email sent successfully to $MailAddress"		}		Catch 		{			Write-Host -ForegroundColor Yellow "   * Exception Message: $($_.Exception.Message)"		}	}}# End Region

# Region Clear-SPSBackup
# ===================================================================================
# Func: Clear-SPSBackup
# Desc: Clean Backup History Files
# ===================================================================================
Function Clear-SPSBackup
{
	Param 	(		[Parameter(Mandatory=$true,Position=0)][xml]$inputFile	)

	If($xmlinput.Configuration.Settings.CleanHistory.Enable -eq "true")
	{
		# Location of spbrtoc.xml
		$BackupFolder = $xmlinput.Configuration.Settings.BackupPath
		$spbrtoc = "$BackupFolder\spbrtoc.xml" 

		If(Test-Path $spbrtoc)
		{
			# Days of backup that will be remaining after backup cleanup. 
			$days = $xmlinput.Configuration.Settings.CleanHistory.Days

			# Import the Sharepoint backup report xml file
			Write-Host -ForegroundColor White " - Get Content of Backup History in file $spbrtoc"
			[xml]$sp = gc $spbrtoc 

			# Find the old backups in spbrtoc.xml 
			$old = $sp.SPBackupRestoreHistory.SPHistoryObject | 
			? { $_.SPStartTime -lt ((get-date).adddays(-$days)) } 
			if ($old -eq $Null)
			{
				Write-Host -ForegroundColor White "--------------------------------------------------------------"
				Write-Host -ForegroundColor White "No reports of backups older than $days days found in spbrtoc.xml.`nspbrtoc.xml isn't changed and no files are removed.`n";
				Write-Host -ForegroundColor White "--------------------------------------------------------------"
				Break
			}
			Else
			{
				# Delete the old backups from the Sharepoint backup report xml file 
				$old | % { $sp.SPBackupRestoreHistory.RemoveChild($_) }
				Write-Host -ForegroundColor White "Delete the old backups from the Sharepoint backup report xml file"

				# Delete the physical folders in which the old backups were located 
				$old | % { Remove-Item $_.SPBackupDirectory -Recurse }
				Write-Host -ForegroundColor White "Delete the physical folders in which the old backups were located"

				# Save the new Sharepoint backup report xml file 
				$sp.Save($spbrtoc)
				Write-Host -ForegroundColor White "--------------------------------------------------------------" 
				Write-Host -ForegroundColor White "Backup(s) entries older than $days days are removed from spbrtoc.xml and harddisc."
				Write-Host -ForegroundColor White "--------------------------------------------------------------"
			}
		}
	}
	Else
	{
		Write-Host -ForegroundColor White "--------------------------------------------------------------" 
		Write-Host -ForegroundColor Yellow " Clean history of Backup is disabled in XML input file. "
		Write-Host -ForegroundColor White "--------------------------------------------------------------"	
	}
}
# End Region

# Region BackupFarm
# ===================================================================================
# Name: 		BackupFarm
# Description:	Backup SharePoint Farm in FULL mode
# ===================================================================================
Function BackupFarm([string]$SharedFolder)
{
	Write-Host -ForegroundColor White "--------------------------------------------------------------" 
	Write-Host -ForegroundColor White " - Full backup of SharePoint Farm in Progress - Please Wait ..."
	Backup-SPFarm -Directory $SharedFolder -BackupMethod full 
	Write-Host -ForegroundColor Green " - Full backup of SharePoint Farm Completed - See logs for details"
	Write-Host -ForegroundColor White "--------------------------------------------------------------" 
}
# Region End

# ===================================================================================
#
# BackUP Script - MAIN Region
#
# ===================================================================================
cls
$Host.UI.RawUI.WindowTitle = " -- BackUP script -- $env:COMPUTERNAME --"

# Logging PowerShell script in rtf file 
$logfolder = Split-Path -parent $MyInvocation.MyCommand.Definition
$logTime = Get-Date -Format yyyy-MM-dd_h-mm
$logFile = "$logfolder\SPSBackUP_script_$logTime.rtf"
$currentuser = ([Security.Principal.WindowsIdentity]::GetCurrent()).Name
Start-Transcript -Path $logFile -Append -Force | out-Null

# Define Variables with Global scope
$BackUpPATH = $xmlinput.Configuration.Settings.BackupPath

$DateStarted = Get-date
Write-Host -ForegroundColor Green "-----------------------------------"
Write-Host -ForegroundColor Green "| Automated Script - BackUp Farm |"
Write-Host -ForegroundColor Green "| Started on: $DateStarted |"
Write-Host -ForegroundColor Green "-----------------------------------"

# Check Permission Level
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{
	Write-Warning "You do not have Administrator rights to run this script!`nPlease re-run this script as an Administrator!"
	Break
} 
else 
{
	# Check Access of Backup Shared Folder
	If ((Test-Path $BackUpPATH) -ne $true)
	{
		Write-Host -ForegroundColor Yellow "-----------------------------------"
		Write-Host -ForegroundColor Red "Script Aborted - Shared Folder $BackUpPATH not found"

		$DateEnded = Get-date
		Write-Host -ForegroundColor Yellow "-----------------------------------"
		Write-Host -ForegroundColor Yellow "| Automated Script - FAILED |"
		Write-Host -ForegroundColor Yellow "| Started on: $DateStarted |"
		Write-Host -ForegroundColor Yellow "| Aborted on: $DateEnded |"
		Write-Host -ForegroundColor Yellow "-----------------------------------"
	}
	Else
	{
		# Add SPSWakeup script in a new scheduled Task		Add-SPSTask -Path $logfolder -InputFile $xmlinput		# Load SharePoint Powershell Snapin
		Load-SharePoint-Powershell		# Get All Web Applications Urls		$WebApps = Get-SPSWebAppUrls			# Add read access for current User account in User Policies settings		Add-SPSUserPolicy $WebApps

		# Clean History Backup Files
		Clear-SPSBackup -inputFile $xmlinput
		
		# Backup SharePoint Farm
		BackupFarm($BackUpPATH)

		$DateEnded = Get-date
		Write-Host -ForegroundColor Green "-----------------------------------"
		Write-Host -ForegroundColor Green "| Automated Script - BackUp Farm |"
		Write-Host -ForegroundColor Green "| Started on: $DateStarted |"
		Write-Host -ForegroundColor Green "| Completed on: $DateEnded |"
		Write-Host -ForegroundColor Green "-----------------------------------"
	}

	Trap {Continue} Stop-Transcript		# Send Email with log file in attachment - For settings see XML input file	Send-SPSLogs -inputFile $xmlinput -MailAttachment $logFile -MailBody $global:MailContent

	Exit
}